<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <title>Test img policy attribute for Bug 1166910</title>
  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>

<!--
Testing that img referrer attribute is honoured correctly
* Speculative parser loads (generate-img-policy-test)
* regular loads (generate-img-policy-test2)
* loading a single image multiple times with different policies (generate-img-policy-test3)
* testing setAttribute and .referrer (generate-setAttribute-test)
* regression tests that meta referrer is still working even if attribute referrers are enabled
https://bugzilla.mozilla.org/show_bug.cgi?id=1166910
-->

<script type="application/javascript;version=1.7">

SimpleTest.waitForExplicitFinish();
var advance = function() { tests.next(); };

/**
 * Listen for notifications from the child.
 * These are sent in case of error, or when the loads we await have completed.
 */
window.addEventListener("message", function(event) {
  if (event.data == "childLoadComplete" ||
      event.data.contains("childLoadComplete")) {
    advance();
  }
});

/**
 * helper to perform an XHR.
 */
function doXHR(aUrl, onSuccess, onFail) {
  var xhr = new XMLHttpRequest();
  xhr.responseType = "json";
  xhr.onload = function () {
    onSuccess(xhr);
  };
  xhr.onerror = function () {
    onFail(xhr);
  };
  xhr.open('GET', aUrl, true);
  xhr.send(null);
}

/**
 * Grabs the results via XHR and passes to checker.
 */
function checkIndividualResults(aTestname, aExpectedImg, aName) {
  doXHR('/tests/dom/base/test/img_referrer_testserver.sjs?action=get-test-results',
        function(xhr) {
          var results = xhr.response;
          info(JSON.stringify(xhr.response));

          for (i in aName) {
            ok(aName[i] in results.tests, aName[i] + " tests have to be performed.");
            is(results.tests[aName[i]].policy, aExpectedImg[i], aTestname + ' --- ' + results.tests[aName[i]].policy + ' (' + results.tests[aName[i]].referrer + ')');
          }

          advance();
        },
        function(xhr) {
          ok(false, "Can't get results from the counter server.");
          SimpleTest.finish();
        });
}

function resetState() {
  doXHR('/tests/dom/base/test/img_referrer_testserver.sjs?action=resetState',
    advance,
    function(xhr) {
      ok(false, "error in reset state");
      SimpleTest.finish();
    });
}

/**
 * testing if img referrer attribute is honoured (1165501)
 */
var tests = (function() {

  // enable referrer attribute
  yield SpecialPowers.pushPrefEnv({"set": [['network.http.enablePerElementReferrer', true]]}, advance);

  var iframe = document.getElementById("testframe");
  var sjs = "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-img-policy-test";

  // setting img unsafe-url and meta origin - unsafe-url shall prevail (should use speculative load)
  yield resetState();
  var name = 'unsaf-url-with-meta-in-origin';
  yield iframe.src = sjs + "&imgPolicy=" + escape('unsafe-url') + "&name=" + name + "&policy=" + escape('origin');
  yield checkIndividualResults("unsafe-url (img) with origin in meta", ["full"], [name]);

  // setting img no-referrer and meta default - no-referrer shall prevail (should use speculative load)
  yield resetState();
  name = 'no-referrer-with-meta-in-origin';
  yield iframe.src = sjs + "&imgPolicy=" + escape('no-referrer')+ "&name=" + name +  "&policy=" + escape('origin');
  yield checkIndividualResults("no-referrer (img) with default in meta", ["none"], [name]);

  // test referrer policy in regular load
  yield resetState();
  sjs = "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-img-policy-test2";
  name = 'regular-load-unsafe-url';
  yield iframe.src = sjs + "&imgPolicy=" + escape('unsafe-url') + "&name=" + name;
  yield checkIndividualResults("unsafe-url in img", ["full"], [name]);

  // test referrer policy in regular load with multiple images
  var policies = ['unsafe-url', 'origin', 'no-referrer'];
  var expected = ["full", "origin", "none"];
  yield resetState();
  sjs = "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-img-policy-test3";
  name = 'multiple-images-'+policies[0]+'-'+policies[1]+'-'+policies[2];
  yield iframe.src = sjs + "&imgPolicy1=" + escape(policies[0]) + "&imgPolicy2=" + escape(policies[1]) + "&imgPolicy3=" + escape(policies[2]) + "&name=" + name;
  yield checkIndividualResults(policies[0]+", "+policies[1]+" and "+policies[2]+" in img", expected, [name+policies[0], name+policies[1], name+policies[2]]);

  policies = ['origin', 'no-referrer', 'unsafe-url'];
  expected = ["origin", "none", "full"];
  yield resetState();
  sjs = "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-img-policy-test3";
  name = 'multiple-images-'+policies[0]+'-'+policies[1]+'-'+policies[2];
  yield iframe.src = sjs + "&imgPolicy1=" + escape(policies[0]) + "&imgPolicy2=" + escape(policies[1]) + "&imgPolicy3=" + escape(policies[2]) + "&name=" + name;
  yield checkIndividualResults(policies[0]+", "+policies[1]+" and "+policies[2]+" in img", expected, [name+policies[0], name+policies[1], name+policies[2]]);

  policies = ['no-referrer', 'origin', 'unsafe-url'];
  expected = ["none", "origin", "full"];
  yield resetState();
  sjs = "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-img-policy-test3";
  name = 'multiple-images-'+policies[0]+'-'+policies[1]+'-'+policies[2];
  yield iframe.src = sjs + "&imgPolicy1=" + escape(policies[0]) + "&imgPolicy2=" + escape(policies[1]) + "&imgPolicy3=" + escape(policies[2]) + "&name=" + name;
  yield checkIndividualResults(policies[0]+", "+policies[1]+" and "+policies[2]+" in img", expected, [name+policies[0], name+policies[1], name+policies[2]]);

  // regression tests that meta referrer is still working even if attribute referrers are enabled
  yield resetState();
  sjs = "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-img-policy-test4";
  name = 'regular-load-no-referrer-meta';
  yield iframe.src = sjs + "&policy=" + escape('no-referrer') + "&name=" + name;
  yield checkIndividualResults("no-referrer in meta (no img referrer policy), speculative load", ["none"], [name]);

  yield resetState();
  sjs = "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-img-policy-test5";
  name = 'regular-load-no-referrer-meta';
  yield iframe.src = sjs + "&policy=" + escape('no-referrer') + "&name=" + name;
  yield checkIndividualResults("no-referrer in meta (no img referrer policy), regular load", ["none"], [name]);

  //test setAttribute
  yield resetState();
  sjs = "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-setAttribute-test1";
  name = 'set-referrer-policy-attribute-before-src';
  yield iframe.src = sjs + "&imgPolicy=" + escape('no-referrer') + "&policy=" + escape('unsafe-url') + "&name=" + name;
  yield checkIndividualResults("no-referrer in img", ["none"], [name]);

  yield resetState();
  sjs = "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-setAttribute-test2";
  name = 'set-referrer-policy-attribute-after-src';
  yield iframe.src = sjs + "&imgPolicy=" + escape('no-referrer') + "&policy=" + escape('unsafe-url') + "&name=" + name;
  yield checkIndividualResults("no-referrer in img", ["none"], [name]);

  yield resetState();
  sjs =
    "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-setAttribute-test2";
  name = 'set-invalid-referrer-policy-attribute-before-src-invalid';
  yield iframe.src = sjs + "&imgPolicy=" + escape('invalid') + "&policy=" + escape('unsafe-url') + "&name=" + name;
  yield checkIndividualResults("unsafe-url in meta, invalid in img", ["full"], [name]);

  yield resetState();
  sjs =
    "/tests/dom/base/test/img_referrer_testserver.sjs?action=generate-setAttribute-test2";
  name = 'set-invalid-referrer-policy-attribute-before-src-invalid';
  yield iframe.src = sjs + "&imgPolicy=" + escape('default') + "&policy=" + escape('unsafe-url') + "&name=" + name;
  yield checkIndividualResults("unsafe-url in meta, default in img", ["full"], [name]);

  // complete.  Be sure to yield so we don't call this twice.
  yield SimpleTest.finish();
})();

</script>
</head>

<body onload="tests.next();">
  <iframe id="testframe"></iframe>

</body>
</html>

